package com.guigu.config;

import com.guigu.handler.MyAccessDeniedHandler;
import com.guigu.handler.MyAuthenticationFailureHandler;
import com.guigu.handler.MyAuthenticationSuccessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;

import javax.annotation.Resource;
import javax.sql.DataSource;

@Configuration
//@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    /**
     * 自定义403
     */
    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;

    //记住我
    @Autowired
    private DataSource dataSource;
    @Autowired
    private PersistentTokenRepository persistentTokenRepository;
    @Resource(name = "userDetailsService")
    private UserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        //表单提交
        http.formLogin()
                //自定义登录页面参数
//                .usernameParameter("username123")
//                .passwordParameter("pwd123")
                //自定义登录页面
                //.loginPage("/login.html")
                .loginPage("/showLogin")   //(***这个必须是get请求***)
                //必须和表单提交的接口一样,会去执行自定义登录逻辑
                .loginProcessingUrl("/login")
                 // 登录成功后跳转的页面 **(只接收post请求)**
                .successForwardUrl("/toMain")
                //使用自定义的
                //.successHandler(new MyAuthenticationSuccessHandler("http://www.baidu.com"))
                // 登录失败跳转页面
                .failureForwardUrl("/toError");
                //.failureHandler(new MyAuthenticationFailureHandler("http://www.4399.com"));

        //授权
        http.authorizeRequests()
                //放行登陆页面,不需要认证
                //.antMatchers("/login.html").permitAll()
                .antMatchers("/showLogin").permitAll()  //----只放行了请求，没有放行模板的登录页面----
                //放行这个登陆失败页面(登录不成功)
                .antMatchers("/error.html").permitAll()
                //放行jpg图片
                .antMatchers("/**/*.jpg").permitAll()
                //权限控制
                //.antMatchers("/main1.html").hasAuthority("admin")
                //.antMatchers("/main1.html").hasAnyAuthority("admin","add")
                //.antMatchers("/main1.html").hasIpAddress("127.0.0.1")
                //所有的请求都必须认证才能访问，必须(**登录成功**)
                .anyRequest().authenticated();
        //异常处理
        http.exceptionHandling()
                .accessDeniedHandler(myAccessDeniedHandler);

        //记住我
        http.rememberMe()
                //设置数据源
                .tokenRepository(persistentTokenRepository)
                //超时时间
                .tokenValiditySeconds(60*2)
                //自定义登录逻辑
                .userDetailsService(userDetailsService);

        //退出
        http.logout()
                //退出成功跳转页面
                .logoutSuccessUrl("/login.html");
        //关闭csrf防护
        //http.csrf().disable();
    }

    @Bean
    public PasswordEncoder getPw() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 记住我
     * @return
     */
    @Bean
    public PersistentTokenRepository persistentTokenRepository(){
        JdbcTokenRepositoryImpl repository = new JdbcTokenRepositoryImpl();
        //设置数据源
        repository.setDataSource(dataSource);
        //自动建表,第一次启动时开启,第二次关闭(注释掉)
        //repository.setCreateTableOnStartup(true);
        return repository;
    }
}
